/*
 * Copyright (c) 2001, Aslak Hellesøy, BEKK Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of BEKK Consulting nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package middlegen.plugins.hibernate.swing;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;

import middlegen.plugins.hibernate.HibernateColumn;
import middlegen.plugins.hibernate.HibernateRelationshipRole;
import middlegen.plugins.hibernate.HibernateTable;
import middlegen.swing.BooleanNodeCheckBox;
import middlegen.util.BooleanNode;

/**
 * This panel renders and modifies a table relationship role.
 *
 * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
 * @created July 16, 2005
 * @version $Revision: 1.1 $
 */
public class JHibernateRelationRoleSettingsPanel extends JPanel {

   /**
    * @todo-javadoc Describe the field
    */
   private HibernateRelationshipRole _relationshipRole;

   /**
    * Describe what the JHibernateRelationRoleSettingsPanel constructor does
    *
    * @todo-javadoc Write javadocs for constructor
    */
   public JHibernateRelationRoleSettingsPanel() {
      super();
   }

   /**
    * Set the relation role for this panel.
    *
    * @param relationshipRole The new RelationRole value.
    */
   public void setRelationRole(HibernateRelationshipRole relationshipRole) {
      _relationshipRole = relationshipRole;
      this.removeAll();

      JPanel firstSectionGroup1 = new JPanel();
      firstSectionGroup1.setLayout(new GridLayout(0, 2, 4, 2));
      add(firstSectionGroup1);
      HibernateTable table = (HibernateTable) relationshipRole.getOrigin();

      firstSectionGroup1.add(createLabel(LocalStrings.TABLE));
      firstSectionGroup1.add(createReadOnly(table.getDestinationClassName()));
      firstSectionGroup1.add(createLabel(LocalStrings.PROPERTY));
      firstSectionGroup1.add(createReadOnly(table.getVariableName(relationshipRole)));

      //then we are a set|list|... and we have a cascade option
      //that can be set.
      String[] options = null;
      if (_relationshipRole.isTargetMany()) {
         options = new String[]{"default", "none", "all", "save-update", "delete", "all-delete-orphan", "delete-orphan"};
      }
      else {
         options = new String[]{"default", "none", "all", "save-update", "delete"};
      }
      firstSectionGroup1.add(createLabel(LocalStrings.CASCADE));
      firstSectionGroup1.add(createCascadeOptions(options));

      //we have a collection so tack on some properties that are specific
      //to a collection
      if (_relationshipRole.isTargetMany()) {
         firstSectionGroup1.add(createLabel(LocalStrings.COLLECTION_TYPE));
         firstSectionGroup1.add(createCollectionTypeOptions());

         firstSectionGroup1.add(createLabel(LocalStrings.COLLECTION_INDEX));
         firstSectionGroup1.add(createCollectionIndexOptions());

         firstSectionGroup1.add(createBoolean(LocalStrings.LAZY, relationshipRole.getLazyNode()));
      }
   }

   /**
    * Sets the collection index for maps/lists attributes of the JHibernateTableSettingsPanel GUI object
    *
    * @todo-javadoc Write javadocs for return value
    * @return Describe the return value
    */
   private JComboBox createCollectionIndexOptions() {

      final JComboBox combo = new JComboBox();
      combo.setRenderer(
               new DefaultListCellRenderer() {
                  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                     HibernateColumn column = (HibernateColumn) value;
                     if (column != null) {
                        value = column.getSqlName();
                     }
                     return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                  }
               });

      Vector columns = new Vector(_relationshipRole.getTarget().getColumns());
      DefaultComboBoxModel model = new DefaultComboBoxModel(columns);
      String currentValue = _relationshipRole.getCollectionIndex();
      combo.setModel(model);
      if (currentValue != null) {
         for (int i = 0; i < columns.size(); i++) {
            HibernateColumn column = (HibernateColumn) columns.get(i);
            if (column.getSqlName().equals(currentValue)) {
               combo.setSelectedItem(column);
               break;
            }
         }

      }

      combo.addActionListener(
               new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                     HibernateColumn selected = (HibernateColumn) combo.getSelectedItem();
                     if (selected == null) {
                        _relationshipRole.setCollectionIndex(null);
                     }
                     else {
                        _relationshipRole.setCollectionIndex(selected.getSqlName());
                     }
                  }
               });
      return combo;
   }

   /**
    * Sets the collection type attributes of the JHibernateTableSettingsPanel GUI object
    *
    * @todo-javadoc Write javadocs for return value
    * @return Describe the return value
    */
   private JComboBox createCollectionTypeOptions() {

      final JComboBox combo = new JComboBox();
      String[] options = new String[]{"default", "set", "bag", "map", "list"};
      DefaultComboBoxModel model = new DefaultComboBoxModel(options);
      String currentValue = _relationshipRole.getCollectionType();
      combo.setModel(model);
      if (currentValue == null) {
         currentValue = "default";
      }
      combo.setSelectedItem(currentValue);
      combo.addActionListener(
               new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                     String selected = (String) combo.getSelectedItem();
                     if (selected.equals("default")) {
                        selected = null;
                     }
                     _relationshipRole.setCollectionType(selected);
                  }
               });
      return combo;
   }


   /**
    * Sets the cascade attributes of the JHibernateTableSettingsPanel GUI object
    *
    * @todo-javadoc Write javadocs for return value
    * @param options The new CascadeOption value.
    * @return Describe the return value
    */
   private JComboBox createCascadeOptions(String[] options) {

      final JComboBox beanCascadeCombo = new JComboBox();
      DefaultComboBoxModel model = new DefaultComboBoxModel(options);
      String currentCascade = _relationshipRole.getCascade();
      beanCascadeCombo.setModel(model);
      if (currentCascade == null) {
         currentCascade = "default";
      }
      beanCascadeCombo.setSelectedItem(currentCascade);
      beanCascadeCombo.addActionListener(
               new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                     String selected = (String) beanCascadeCombo.getSelectedItem();
                     if (selected.equals("default")) {
                        selected = null;
                     }
                     _relationshipRole.setCascade(selected);
                  }
               });
      return beanCascadeCombo;
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for return value
    * @param identifier Describe what the parameter does
    * @param node Describe what the parameter does
    * @return Describe the return value
    */
   private BooleanNodeCheckBox createBoolean(String identifier, BooleanNode node) {
      BooleanNodeCheckBox checkbox = new BooleanNodeCheckBox(LocalStrings.getMsg(identifier), node);
      return checkbox;
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for return value
    * @param identifier Describe what the parameter does
    * @return Describe the return value
    */
   private JLabel createLabel(String identifier) {
      return new JLabel(LocalStrings.getMsg(identifier));
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for return value
    * @param text Describe what the parameter does
    * @return Describe the return value
    */
   private JTextField createReadOnly(String text) {
      JTextField field = new JTextField(text);
      field.setEditable(false);
      return field;
   }
}
